package com.erp.erp_ui.Activiti;

import com.erp.erp_entitys.Activiti.LeaveTaskEntity;
import com.erp.erp_entitys.Process.ProcessEntity;
import com.erp.erp_entitys.Role.RoleEntity;
import com.erp.erp_entitys.Role.RoleExample;
import com.erp.erp_entitys.RoleGroupMember.RoleGroupMemberEntity;
import com.erp.erp_entitys.User.UserEntity;
import com.erp.erp_entitys.User.UserEntityExample;
import com.erp.erp_servers.Role.imp.ImpRoleService;
import com.erp.erp_servers.RoleGroupMember.imp.ImpRoleGroupMemberService;
import com.erp.erp_servers.User.imp.ImpUserSerice;
import com.erp.erp_ui.Activiti.service.ImpProcessSerivce;
import com.erp.quertz.SpringUtil;
import org.activiti.bpmn.model.BpmnModel;
import org.activiti.bpmn.model.FlowElement;
import org.activiti.bpmn.model.Process;
import org.activiti.bpmn.model.UserTask;
import org.activiti.engine.*;
import org.activiti.engine.delegate.Expression;
import org.activiti.engine.form.TaskFormData;
import org.activiti.engine.history.HistoricActivityInstance;
import org.activiti.engine.history.HistoricTaskInstance;
import org.activiti.engine.impl.RepositoryServiceImpl;
import org.activiti.engine.impl.bpmn.behavior.UserTaskActivityBehavior;
import org.activiti.engine.impl.identity.Authentication;
import org.activiti.engine.impl.javax.el.ExpressionFactory;
import org.activiti.engine.impl.javax.el.ValueExpression;
import org.activiti.engine.impl.juel.ExpressionFactoryImpl;
import org.activiti.engine.impl.juel.SimpleContext;
import org.activiti.engine.impl.persistence.entity.ProcessDefinitionEntity;
import org.activiti.engine.impl.persistence.entity.TaskEntity;
import org.activiti.engine.impl.pvm.PvmActivity;
import org.activiti.engine.impl.pvm.PvmTransition;
import org.activiti.engine.impl.pvm.process.ActivityImpl;
import org.activiti.engine.impl.pvm.process.ProcessDefinitionImpl;
import org.activiti.engine.impl.pvm.process.TransitionImpl;
import org.activiti.engine.impl.task.TaskDefinition;
import org.activiti.engine.repository.Deployment;
import org.activiti.engine.repository.ProcessDefinition;
import org.activiti.engine.runtime.Execution;
import org.activiti.engine.runtime.ProcessInstance;
import org.activiti.engine.task.Comment;
import org.activiti.engine.task.Task;
import org.apache.commons.lang3.StringUtils;

import java.text.SimpleDateFormat;
import java.util.*;


/**
 * 流程操作核心类<br>
 * 此核心类主要处理：驳回流程、取回流程、清空指定活动节点流向 、提交流程/流程转向、中止流程(特权人直接审批通过等)、挂起等核心操作<br>
 *
 *
 */
public class  ProcessService  {

    ImpUserSerice userService= SpringUtil.getBean(ImpUserSerice.class);

    ImpRoleGroupMemberService roleGroupMemberService=SpringUtil.getBean(ImpRoleGroupMemberService.class);

    ImpRoleService roleService=SpringUtil.getBean(ImpRoleService.class);


    private static ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
    private static RepositoryService repositoryService = processEngine.getRepositoryService();

    private static RuntimeService runtimeService = processEngine.getRuntimeService();


    private static TaskService taskService = processEngine.getTaskService();


    private static FormService formService = processEngine.getFormService();


    private static HistoryService historyService = processEngine.getHistoryService();

    private static IdentityService identityService=processEngine.getIdentityService();
    /**
     * 驳回流程
     *
     * @param taskId
     *            当前任务ID
     * @param activityId
     *            驳回节点ID
     * @param variables
     *            流程存储参数
     * @throws Exception
     */
    public static void backProcess(String taskId, String activityId,Map<String, Object> variables,String comment,String userName) throws Exception {
        if (StringUtils.isEmpty(activityId)) {
            throw new Exception("驳回目标节点ID为空！");
        }

        // 查找所有并行任务节点，同时驳回
        List<Task> taskList = findTaskListByKey(findProcessInstanceByTaskId(
                taskId).getId(), findTaskById(taskId).getTaskDefinitionKey());
        for (Task task : taskList) {
            commitProcess(task.getId(), variables, activityId,comment,userName);
        }
    }


    /**
     * 取回流程
     *
     * @param taskId
     *            当前任务ID
     * @param activityId
     *            取回节点ID
     * @throws Exception
     */
    public static void callBackProcess(String taskId, String activityId,String comment,String userName)  throws Exception {
        if (StringUtils.isEmpty(activityId)) {
            throw new Exception("目标节点ID为空！");
        }

        // 查找所有并行任务节点，同时取回
        List<Task> taskList = findTaskListByKey(findProcessInstanceByTaskId(
                taskId).getId(), findTaskById(taskId).getTaskDefinitionKey());
        for (Task task : taskList) {
            commitProcess(task.getId(), null, activityId,comment,userName);
        }
    }


    /**
     * 清空指定活动节点流向
     *
     * @param activityImpl
     *            活动节点
     * @return 节点流向集合
     */
    private static List<PvmTransition> clearTransition(ActivityImpl activityImpl) {
        // 存储当前节点所有流向临时变量
        List<PvmTransition> oriPvmTransitionList = new ArrayList<PvmTransition>();
        // 获取当前节点所有流向，存储到临时变量，然后清空
        List<PvmTransition> pvmTransitionList = activityImpl
                .getOutgoingTransitions();
        for (PvmTransition pvmTransition : pvmTransitionList) {
            oriPvmTransitionList.add(pvmTransition);
        }
        pvmTransitionList.clear();

        return oriPvmTransitionList;
    }


    /**
     * 提交流程/流程转向
     * @param taskId
     *            当前任务ID
     * @param variables
     *            流程变量
     * @param activityId
     *            流程转向执行任务节点ID<br>
     *            此参数为空，默认为提交操作
     * @param  comment 批注
     * @param  userName 当前操作者名字
     * @throws Exception
     */
    public static void commitProcess(String taskId, Map<String, Object> variables,    String activityId,String comment,String userName) throws Exception {
        if (variables == null) {
            variables = new HashMap<String, Object>();
        }
        // 跳转节点为空，默认提交操作
        if (StringUtils.isEmpty(activityId)) {
            // 由于流程用户上下文对象是线程独立的，所以要在需要的位置设置，要保证设置和获取操作在同一个线程中
            Authentication.setAuthenticatedUserId(userName);//批注人的名称  一定要写，不然查看的时候不知道人物信息
            // 添加批注信息
            taskService.addComment(taskId, null, comment);//comment为批注内容
            taskService.complete(taskId, variables);
        } else {// 流程转向操作
            turnTransition(taskId, activityId, variables,comment,userName);
        }
    }


    /**
     * 中止流程(特权人直接审批通过等)
     *
     * @param taskId
     */
    public static void endProcess(String taskId,String comment,String userName) throws Exception {
        ActivityImpl endActivity = findActivitiImpl(taskId, "end");
        commitProcess(taskId, null, endActivity.getId(),comment,userName);
    }


    /**
     * 根据流入任务集合，查询最近一次的流入任务节点
     *
     * @param processInstance
     *            流程实例
     * @param tempList
     *            流入任务集合
     * @return
     */
    public static ActivityImpl filterNewestActivity(ProcessInstance processInstance,  List<ActivityImpl> tempList) {
        while (tempList.size() > 0) {
            ActivityImpl activity_1 = tempList.get(0);
            HistoricActivityInstance activityInstance_1 = findHistoricUserTask(
                    processInstance, activity_1.getId());
            if (activityInstance_1 == null) {
                tempList.remove(activity_1);
                continue;
            }

            if (tempList.size() > 1) {
                ActivityImpl activity_2 = tempList.get(1);
                HistoricActivityInstance activityInstance_2 = findHistoricUserTask(
                        processInstance, activity_2.getId());
                if (activityInstance_2 == null) {
                    tempList.remove(activity_2);
                    continue;
                }

                if (activityInstance_1.getEndTime().before(
                        activityInstance_2.getEndTime())) {
                    tempList.remove(activity_1);
                } else {
                    tempList.remove(activity_2);
                }
            } else {
                break;
            }
        }
        if (tempList.size() > 0) {
            return tempList.get(0);
        }
        return null;
    }


    /**
     * 根据任务ID和节点ID获取活动节点 <br>
     *
     * @param taskId
     *            任务ID
     * @param activityId
     *            活动节点ID <br>
     *            如果为null或""，则默认查询当前活动节点 <br>
     *            如果为"end"，则查询结束节点 <br>
     *
     * @return
     * @throws Exception
     */
    public static ActivityImpl findActivitiImpl(String taskId, String activityId) throws Exception {
        // 取得流程定义
        ProcessDefinitionEntity processDefinition = findProcessDefinitionEntityByTaskId(taskId);

        // 获取当前活动节点ID
        if (StringUtils.isEmpty(activityId)) {
            activityId = findTaskById(taskId).getTaskDefinitionKey();
        }

        // 根据流程定义，获取该流程实例的结束节点
        if (activityId.toUpperCase().equals("END")) {
            for (ActivityImpl activityImpl : processDefinition.getActivities()) {
                List<PvmTransition> pvmTransitionList = activityImpl
                        .getOutgoingTransitions();
                if (pvmTransitionList.isEmpty()) {
                    return activityImpl;
                }
            }
        }

        // 根据节点ID，获取对应的活动节点
        ActivityImpl activityImpl = ((ProcessDefinitionImpl) processDefinition)
                .findActivity(activityId);

        return activityImpl;
    }


    /**
     * 根据当前任务ID，查询可以驳回的任务节点
     *
     * @param taskId
     *            当前任务ID
     */
    public static List<ActivityImpl> findBackAvtivity(String taskId) throws Exception {
        List<ActivityImpl> rtnList =  iteratorBackActivity(taskId, findActivitiImpl(taskId,
                null), new ArrayList<ActivityImpl>(),
                new ArrayList<ActivityImpl>());
        return reverList(rtnList);
    }

    /**
     * 查询指定任务节点的最新记录
     *
     * @param processInstance
     *            流程实例
     * @param activityId
     * @return
     */
    private static HistoricActivityInstance findHistoricUserTask(  ProcessInstance processInstance, String activityId) {
        HistoricActivityInstance rtnVal = null;
        // 查询当前流程实例审批结束的历史节点
        List<HistoricActivityInstance> historicActivityInstances = historyService
                .createHistoricActivityInstanceQuery().activityType("userTask")
                .processInstanceId(processInstance.getId()).activityId(
                        activityId).finished()
                .orderByHistoricActivityInstanceEndTime().desc().list();
        if (historicActivityInstances.size() > 0) {
            rtnVal = historicActivityInstances.get(0);
        }

        return rtnVal;
    }

    /**
     * 根据当前节点，查询输出流向是否为并行终点，如果为并行终点，则拼装对应的并行起点ID
     *
     * @param activityImpl
     *            当前节点
     * @return
     */
    private static String findParallelGatewayId(ActivityImpl activityImpl) {
        List<PvmTransition> incomingTransitions = activityImpl
                .getOutgoingTransitions();
        for (PvmTransition pvmTransition : incomingTransitions) {
            TransitionImpl transitionImpl = (TransitionImpl) pvmTransition;
            activityImpl = transitionImpl.getDestination();
            String type = (String) activityImpl.getProperty("type");
            if ("parallelGateway".equals(type)) {// 并行路线
                String gatewayId = activityImpl.getId();
                String gatewayType = gatewayId.substring(gatewayId
                        .lastIndexOf("_") + 1);
                if ("END".equals(gatewayType.toUpperCase())) {
                    return gatewayId.substring(0, gatewayId.lastIndexOf("_"))
                            + "_start";
                }
            }
        }
        return null;
    }

    /**
     * 根据任务ID获取流程定义
     *
     * @param taskId
     *            任务ID
     * @return
     * @throws Exception
     */
    public static ProcessDefinitionEntity findProcessDefinitionEntityByTaskId( String taskId) throws Exception {
        // 取得流程定义
        ProcessDefinitionEntity processDefinition = (ProcessDefinitionEntity) ((RepositoryServiceImpl) repositoryService)
                .getDeployedProcessDefinition(findTaskById(taskId)
                        .getProcessDefinitionId());

        if (processDefinition == null) {
            throw new Exception("流程定义未找到!");
        }

        return processDefinition;
    }

    /**
     * 根据任务ID获取对应的流程实例
     *
     * @param taskId
     *            任务ID
     * @return
     * @throws Exception
     */
    public static ProcessInstance findProcessInstanceByTaskId(String taskId)  throws Exception {
        // 找到流程实例
        ProcessInstance processInstance = runtimeService
                .createProcessInstanceQuery().processInstanceId(
                        findTaskById(taskId).getProcessInstanceId())
                .singleResult();
        if (processInstance == null) {
            throw new Exception("流程实例未找到!");
        }
        return processInstance;
    }

    /**
     * 根据任务ID获得任务实例
     *
     * @param taskId
     *            任务ID
     * @return
     * @throws Exception
     */
    private static TaskEntity findTaskById(String taskId) throws Exception {
        TaskEntity task = (TaskEntity) taskService.createTaskQuery().taskId(
                taskId).singleResult();
        if (task == null) {
            throw new Exception("任务实例未找到!");
        }
        return task;
    }


    /**
     * 根据流程实例ID和任务key值查询所有同级任务集合
     *
     * @param processInstanceId
     * @param key
     * @return
     */
    private static List<Task> findTaskListByKey(String processInstanceId, String key) {
        return taskService.createTaskQuery().processInstanceId(
                processInstanceId).taskDefinitionKey(key).list();
    }


    /**
     * 迭代循环流程树结构，查询当前节点可驳回的任务节点
     *
     * @param taskId
     *            当前任务ID
     * @param currActivity
     *            当前活动节点
     * @param rtnList
     *            存储回退节点集合
     * @param tempList
     *            临时存储节点集合（存储一次迭代过程中的同级userTask节点）
     * @return 回退节点集合
     */
    private static List<ActivityImpl> iteratorBackActivity(String taskId,   ActivityImpl currActivity, List<ActivityImpl> rtnList,
                                                           List<ActivityImpl> tempList) throws Exception {
        // 查询流程定义，生成流程树结构
        ProcessInstance processInstance = findProcessInstanceByTaskId(taskId);

        // 当前节点的流入来源
        List<PvmTransition> incomingTransitions = currActivity
                .getIncomingTransitions();
        // 条件分支节点集合，userTask节点遍历完毕，迭代遍历此集合，查询条件分支对应的userTask节点
        List<ActivityImpl> exclusiveGateways = new ArrayList<ActivityImpl>();
        // 并行节点集合，userTask节点遍历完毕，迭代遍历此集合，查询并行节点对应的userTask节点
        List<ActivityImpl> parallelGateways = new ArrayList<ActivityImpl>();
        // 遍历当前节点所有流入路径
        for (PvmTransition pvmTransition : incomingTransitions) {
            TransitionImpl transitionImpl = (TransitionImpl) pvmTransition;
            ActivityImpl activityImpl = transitionImpl.getSource();
            String type = (String) activityImpl.getProperty("type");
            /**
             * 并行节点配置要求：<br>
             * 必须成对出现，且要求分别配置节点ID为:XXX_start(开始)，XXX_end(结束)
             */
            if ("parallelGateway".equals(type)) {// 并行路线
                String gatewayId = activityImpl.getId();
                String gatewayType = gatewayId.substring(gatewayId
                        .lastIndexOf("_") + 1);
                if ("START".equals(gatewayType.toUpperCase())) {// 并行起点，停止递归
                    return rtnList;
                } else {// 并行终点，临时存储此节点，本次循环结束，迭代集合，查询对应的userTask节点
                    parallelGateways.add(activityImpl);
                }
            } else if ("startEvent".equals(type)) {// 开始节点，停止递归
                return rtnList;
            } else if ("userTask".equals(type)) {// 用户任务
                tempList.add(activityImpl);
            } else if ("exclusiveGateway".equals(type)) {// 分支路线，临时存储此节点，本次循环结束，迭代集合，查询对应的userTask节点
                currActivity = transitionImpl.getSource();
                exclusiveGateways.add(currActivity);
            }
        }

        /**
         * 迭代条件分支集合，查询对应的userTask节点
         */
        for (ActivityImpl activityImpl : exclusiveGateways) {
            iteratorBackActivity(taskId, activityImpl, rtnList, tempList);
        }

        /**
         * 迭代并行集合，查询对应的userTask节点
         */
        for (ActivityImpl activityImpl : parallelGateways) {
            iteratorBackActivity(taskId, activityImpl, rtnList, tempList);
        }

        /**
         * 根据同级userTask集合，过滤最近发生的节点
         */
        currActivity = filterNewestActivity(processInstance, tempList);
        if (currActivity != null) {
            // 查询当前节点的流向是否为并行终点，并获取并行起点ID
            String id = findParallelGatewayId(currActivity);
            if (StringUtils.isEmpty(id)) {// 并行起点ID为空，此节点流向不是并行终点，符合驳回条件，存储此节点
                rtnList.add(currActivity);
            } else {// 根据并行起点ID查询当前节点，然后迭代查询其对应的userTask任务节点
                currActivity = findActivitiImpl(taskId, id);
            }

            // 清空本次迭代临时集合
            tempList.clear();
            // 执行下次迭代
            iteratorBackActivity(taskId, currActivity, rtnList, tempList);
        }
        return rtnList;
    }


    /**
     * 还原指定活动节点流向
     *
     * @param activityImpl
     *            活动节点
     * @param oriPvmTransitionList
     *            原有节点流向集合
     */
    private static void restoreTransition(ActivityImpl activityImpl,
                                          List<PvmTransition> oriPvmTransitionList) {
        // 清空现有流向
        List<PvmTransition> pvmTransitionList = activityImpl
                .getOutgoingTransitions();
        pvmTransitionList.clear();
        // 还原以前流向
        for (PvmTransition pvmTransition : oriPvmTransitionList) {
            pvmTransitionList.add(pvmTransition);
        }
    }

    /**
     * 反向排序list集合，便于驳回节点按顺序显示
     *
     * @param list
     * @return
     */
    private static List<ActivityImpl> reverList(List<ActivityImpl> list) {
        List<ActivityImpl> rtnList = new ArrayList<ActivityImpl>();
        // 由于迭代出现重复数据，排除重复
        for (int i = list.size(); i > 0; i--) {
            if (!rtnList.contains(list.get(i - 1)))
                rtnList.add(list.get(i - 1));
        }
        return rtnList;
    }

    /**
     * 转办流程
     *
     * @param taskId
     *            当前任务节点ID
     * @param userCode
     *            被转办人Code
     */
    public static void transferAssignee(String taskId, String userCode) {
        taskService.setAssignee(taskId, userCode);
    }

    /**
     * 流程转向操作
     *
     * @param taskId
     *            当前任务ID
     * @param activityId
     *            目标节点任务ID
     * @param variables
     *            流程变量
     * @throws Exception
     */
    private static void turnTransition(String taskId, String activityId,
                                       Map<String, Object> variables,String comment,String userName) throws Exception {
        // 当前节点
        ActivityImpl currActivity = findActivitiImpl(taskId, null);
        // 清空当前流向
        List<PvmTransition> oriPvmTransitionList = clearTransition(currActivity);

        // 创建新流向
        TransitionImpl newTransition = currActivity.createOutgoingTransition();
        // 目标节点
        ActivityImpl pointActivity = findActivitiImpl(taskId, activityId);
        // 设置新流向的目标节点
        newTransition.setDestination(pointActivity);

        // 由于流程用户上下文对象是线程独立的，所以要在需要的位置设置，要保证设置和获取操作在同一个线程中
        Authentication.setAuthenticatedUserId(userName);//批注人的名称  一定要写，不然查看的时候不知道人物信息
        // 添加批注信息
        taskService.addComment(taskId, null, comment);//comment为批注内容

        // 执行转向任务
        taskService.complete(taskId, variables);
        // 删除目标节点新流入
        pointActivity.getIncomingTransitions().remove(newTransition);

        // 还原以前流向
        restoreTransition(currActivity, oriPvmTransitionList);
    }

   /* public static InputStream getImageStream(String taskId) throws Exception{
    	ProcessDefinitionEntity pde = findProcessDefinitionEntityByTaskId(taskId);
    	InputStream imageStream = ProcessDiagramGenerator.generateDiagram(
				pde, "png",
		runtimeService.getActiveActivityIds(findProcessInstanceByTaskId(taskId).getId()));
    	return imageStream;
    }*/

    /**
     * 发起流程，传入流程参数，并返回流程id
     * @param processKey
     * @param map
     * @return
     */
    public static String  startProcess(String processKey,Map<String, Object> map){
        ProcessInstance processInstance = runtimeService.startProcessInstanceByKey(processKey,map);
        return processInstance.getDeploymentId();
    }

    /**
     * 启动流程
     * @param processKey
     * @Param bid 业务尖
     * @return
     */

    public static String startProcess(String processKey,String bid){
        ProcessInstance processInstance = runtimeService.startProcessInstanceByKey(processKey,bid);
        return processInstance.getId();
    }
    /**
     *
     * @param processKey 流程定义尖
     * @param bid 业务主键
     * @param variables 流程参数
     * @return
     */

    public static String startProcess(String processKey,String bid,Map<String, Object> variables,String startUserCode ){
       /* try{
            getFristTaskSpr(processKey);
        }catch (Exception e){

        }*/

        identityService.setAuthenticatedUserId(startUserCode);
        ProcessInstance processInstance = runtimeService.startProcessInstanceByKey(processKey,bid,variables);
        //根据流程定义key、与bid来更新业务表流程状态
        ProcessEntity process=new ProcessEntity();
        String code=variables.get("code")==null?"":variables.get("code").toString();
        String totalCost=variables.get("totalCost")==null?"":variables.get("totalCost").toString();

        process.setCode(code);
        process.setTotalCost(totalCost);
        process.setProcessid(processInstance.getId());

        ImpProcessSerivce processSerivce=SpringUtil.getBean(ImpProcessSerivce.class);

        processSerivce.insert(process);

        try {
            List<LeaveTaskEntity> leaveTaskEntities = ProcessService.queryToDoTasks2(startUserCode, processInstance.getProcessDefinitionKey());
            LeaveTaskEntity leaveTaskEntity=new LeaveTaskEntity();
            for(LeaveTaskEntity lte:leaveTaskEntities){
                if(lte.getProcessInstanceId().equals(processInstance.getId())){
                    leaveTaskEntity=lte;
                    break;
                }
            }

            String taskId=leaveTaskEntity.getTaskid();
            ActivityImpl activitiImpl = ProcessService.findActivitiImpl(taskId, null);
            variables.putAll( getNextSpr( taskId));//获取下一节点审批人
            commitProcess(taskId,variables,null,"提交",startUserCode);

        }catch (Exception e){

        }



        return processInstance.getId();
    }
    /////////////////////////////////

    /**
     * 获取下一节点审批人
     * @param taskId
     * @return
     * @throws Exception
     */
    public static Map<String, Object> getNextSpr(String taskId)throws Exception{
        ProcessService ps=new ProcessService();
        Map<String, Object> map=new HashMap<>();
        TaskDefinition nextTask = ProcessService.getNextTask(taskId);
        if(nextTask==null) return map;
        Expression assigneeExpression = nextTask.getAssigneeExpression();
        Set<Expression> candidateUserIdExpressions = nextTask.getCandidateUserIdExpressions();
        Set<Expression> candidateGroupIdExpressions = nextTask.getCandidateGroupIdExpressions();
        String a="";
        String u="";
        String g="";
        String ru="";
        String rg="";
        if(candidateUserIdExpressions.size() >0){
           /* String role=cl(candidateUserIdExpressions.iterator().next());
            variables.put(role,getUserByRole(role));*/
            ru = candidateUserIdExpressions.iterator().next().getExpressionText().replace("${","").replace("}","");
            u=ps.getUserByRole(ru);
        }
        if(candidateGroupIdExpressions.size()>0){
            rg= candidateGroupIdExpressions.iterator().next().getExpressionText().replace("${","").replace("}","");
            g=ps.getUserGroupByRole(rg);
        }
        if(assigneeExpression !=null){
            a=assigneeExpression.getExpressionText();
        }

        /*if(a !=null)   return a;*/
        if(!ru.equals("")){
            map.put(ru,u);
        }
        if(!rg.equals("")) {
            map.put(rg,g);
        }
        if(!a.equals("")  && a.indexOf("$") !=-1){
            map.put(a.replace("${","").replace("}",""),a);
        }

        return map;
    }
    private  String getUserByRole(String role){
        UserEntityExample example=new UserEntityExample();
        UserEntityExample.Criteria criteria = example.createCriteria();
        criteria.andRolesLike("%"+role+"%");

       // ImpCustomerService customerService = SpringUtil.getBean(ImpCustomerService.class);

        List<UserEntity> userEntities = userService.selectByExample(example);
        //  List<String> list=new ArrayList<>();
        String user="";
        for(int i=0;i<userEntities.size();i++){
            if(i==userEntities.size()-1){
                user+=userEntities.get(i).getCode();
            }else{
                user+=userEntities.get(i).getCode()+",";
            }

        }
        return user;
    }
    private  String getUserGroupByRole(String grouprole){
        try{
            String users="";
            List<RoleEntity> roleEntities=new ArrayList<RoleEntity>();

            RoleGroupMemberEntity record=new RoleGroupMemberEntity();
            record.setGroupCode(grouprole);
            List<RoleGroupMemberEntity> roleGroupMemberEntities = roleGroupMemberService.selectByExample(record);
            if(roleGroupMemberEntities.size()==0) return users;
            List<String> listRoleCode=new ArrayList<String>();
            for(int i=0;i<roleGroupMemberEntities.size();i++){
                listRoleCode.add(roleGroupMemberEntities.get(i).getRoleCode());
            }
            RoleExample example=new RoleExample();
            RoleExample.Criteria criteria = example.createCriteria();
            criteria.andCodeIn(listRoleCode);
            roleEntities = roleService.selectByExample(example);
            //获取人
            UserEntityExample example1=new UserEntityExample();
            UserEntityExample.Criteria criteria1 = example1.createCriteria();
            for(int i=0;i<roleEntities.size();i++){
                criteria1.andRolesLike("%"+roleEntities.get(i).getCode()+"%");
            }
            List<UserEntity> userEntities = userService.selectByExample(example1);
            for(int i=0;i<userEntities.size();i++){
                if(i==userEntities.size()-1){
                    users+=userEntities.get(i).getCode();
                }else{
                    users+=userEntities.get(i).getCode()+",";
                }
            }
            return users;
        }catch (Exception e){
            e.printStackTrace();
            return "";
        }

    }
///////////////////////////////

    /**
     * 部署流程
     * @param processKey
     * @param processName
     * @return
     */
    public static String deploy(String processKey,String processName){

        Deployment deploy= repositoryService.createDeployment()
                //添加bpmn资源
                    .addClasspathResource("bpm/"+processKey+".bpmn20.xml")
                //添加图片文件资源
                .addClasspathResource("bpm/"+processKey+".bpmn20.png")
                .name(processName)
                .deploy();
        return deploy.getId();

    }
    /**
     * 查询用户待办任务列表。
     *
     * @param assignee 用户
     * @return 任务列表
     */
    public static List<LeaveTaskEntity> queryToDoTasks2(String assignee,String processKey) throws Exception {
        List<Task> taskList  = taskService.createTaskQuery().taskAssignee(assignee).list();
        List<Task> list = taskService.createTaskQuery().taskCandidateGroup(assignee).list();
        List<Task> list1 = taskService.createTaskQuery().taskCandidateUser(assignee).list();

        taskList.addAll(list);
        taskList.addAll(list1);
      /*  String formKey = ProcessService.getFormInfo(taskId);//表单
        String businessKey = ProcessService.getBusinessKey(taskId);*/
        List<LeaveTaskEntity> leaveTasks = new ArrayList<>();
        for (Task task : taskList) {
            if(!task.getProcessDefinitionId().split(":")[0].equals(processKey)) continue;
            LeaveTaskEntity leaveTask = new LeaveTaskEntity();
            leaveTask.setTaskid(task.getId());
            leaveTask.setName(task.getName());
            leaveTask.setProcessInstanceId(task.getProcessInstanceId());
            leaveTask.setProcessDefinitionId(task.getProcessDefinitionId());
            ProcessDefinition processDefinition = queryProcessDefinition(task.getProcessDefinitionId());
            SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
            leaveTask.setCreatetime(formatter.format(task.getCreateTime()));
            leaveTask.setProcessDfName(processDefinition.getName());
            String businessKey = ProcessService.getBusinessKey(task.getId());
            String startUser = ProcessService.getStartUser(task.getId());
            leaveTask.setBusinessKey(businessKey);
            leaveTask.setStartUser(startUser);
            leaveTasks.add(leaveTask);
        }
        return leaveTasks;
    }
    /**
     * 查询用户待办任务列表。
     *
     * @param assignee 用户
     * @return 任务列表
     */
    public static List<LeaveTaskEntity> queryToDoTasks(String assignee) {
        List<Task> taskList  = taskService.createTaskQuery().taskAssignee(assignee).list();
        List<Task> list = taskService.createTaskQuery().taskCandidateGroup(assignee).list();
        List<Task> list1 = taskService.createTaskQuery().taskCandidateUser(assignee).list();

        taskList.addAll(list);
        taskList.addAll(list1);

        List<LeaveTaskEntity> leaveTasks = new ArrayList<>();
        for (Task task : taskList) {
            LeaveTaskEntity leaveTask = new LeaveTaskEntity();
            leaveTask.setTaskid(task.getId());
            leaveTask.setName(task.getName());
            leaveTask.setProcessInstanceId(task.getProcessInstanceId());
            leaveTask.setProcessDefinitionId(task.getProcessDefinitionId());
            ProcessDefinition processDefinition = queryProcessDefinition(task.getProcessDefinitionId());
            SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
            leaveTask.setCreatetime(formatter.format(task.getCreateTime()));
            leaveTask.setProcessDfName(processDefinition.getName());
            leaveTasks.add(leaveTask);
        }
        return leaveTasks;
    }

    /**
     * 查询已处理任务列表。
     *
     * @param assignee 用户
     * @return 已处理任务列表
     */
    public static  List<LeaveTaskEntity> queryDoneTasks(String assignee) {
        List<HistoricTaskInstance> taskList  = historyService.createHistoricTaskInstanceQuery()
                .taskAssignee(assignee)
                .finished()
                .list();

        List<LeaveTaskEntity> leaveTasks = new ArrayList<>();
        for (HistoricTaskInstance task : taskList) {
            LeaveTaskEntity leaveTask = new LeaveTaskEntity();
            leaveTask.setTaskid(task.getId());
            leaveTask.setName(task.getName());
            leaveTask.setProcessInstanceId(task.getProcessInstanceId());
            leaveTask.setProcessDefinitionId(task.getProcessDefinitionId());
            leaveTasks.add(leaveTask);
        }
        return leaveTasks;
    }

    /**
     * 根据流程实例id查询当前活动节点id
     * @param processId
     * @return
     */
    public static String  queryActivityIdByProcessId(String processId){
        String activityId = runtimeService.createProcessInstanceQuery().processInstanceId(processId).singleResult().getActivityId();
        return activityId;
    }

    /**
     * 根据流程定义key查询流程定义
     * @param processDefkey
     * @return
     */
    public static ProcessDefinition queryProcessDefinition(String processDefkey){
        ProcessDefinition processDefinition=null;
        if(processDefkey.indexOf(":") != -1){
            processDefinition=repositoryService.createProcessDefinitionQuery().processDefinitionId(processDefkey).singleResult();
        }else{
             processDefinition=repositoryService.createProcessDefinitionQuery() // 创建流程定义查询
                    .processDefinitionKey(processDefkey) // 根据流程定义id查询
                    .orderByProcessDefinitionVersion()
                    .desc()
                    .list()
                    .get(0);
        }

       // List<Comment> processInstanceComments = taskService.getProcessInstanceComments("");
        return processDefinition;
    }

    /**
     * 查询 审批日志
     * @param taskId
     * @return
     */
    public static List<Comment> getProcessComments(String taskId)throws Exception {
        List<Comment> historyCommnets = new ArrayList<>();
       // String startUser = ProcessService.getStartUser(taskId);
       // String startUser = ProcessService.getStartUser(taskId);

//         1) 获取流程实例的ID
        Task task = taskService.createTaskQuery().taskId(taskId).singleResult();
        ProcessInstance pi =runtimeService.createProcessInstanceQuery().processInstanceId(task.getProcessInstanceId()).singleResult();
//       2）通过流程实例查询所有的(用户任务类型)历史活动
        List<HistoricActivityInstance> hais = historyService.createHistoricActivityInstanceQuery().processInstanceId(pi.getId()).activityType("userTask").list();

        //       3）查询每个历史任务的批注
        for (HistoricActivityInstance hai : hais) {
            String historytaskId = hai.getTaskId();
            List<Comment> comments = taskService.getTaskComments(historytaskId);
            // 4）如果当前任务有批注信息，添加到集合中
            if(comments!=null && comments.size()>0){
                historyCommnets.addAll(comments);
            }
        }
//       5）返回
        return historyCommnets;
    }

    /**
     * 获取自定义表单
     * @param taskId
     * @return
     */
    public static String getFormInfo(String taskId){
        TaskFormData formData = formService.getTaskFormData(taskId);
        String formKey = formData.getFormKey();
        return formKey;
    }

    /**
     * 根据taskId获取业务主键
     * @param taskId
     * @return
     * @throws Exception
     */
    public static String getBusinessKey(String taskId)throws Exception{
        //根据任务id获取流程实例
        ProcessInstance processInstance=ProcessService.findProcessInstanceByTaskId(taskId);
        String businessKey = processInstance.getBusinessKey();
        return businessKey;
    }
    public  static String getStartUser(String taskId)throws Exception{
        ProcessInstance processInstance=ProcessService.findProcessInstanceByTaskId(taskId);
        String startUserId = historyService.createHistoricProcessInstanceQuery().processInstanceId(processInstance.getId()).singleResult().getStartUserId();
        return startUserId;
    }

    /**
     * 获取首节点审批人
     * @param
     * @return
     * @throws Exception
     */
    public static UserTask getFristTaskSpr(String processDefId)throws Exception{
        //获取流程定义
        ProcessDefinition processDefinition = queryProcessDefinition(processDefId);

        BpmnModel bpmnModel = repositoryService.getBpmnModel(processDefinition.getId());
        Process process = bpmnModel.getProcessById(processDefId);

        //获取第一个节点信息
        Collection<FlowElement> flowElements = process.getFlowElements();
        UserTask userTask=null;
        for(FlowElement flowElement:flowElements){
            if (flowElement instanceof UserTask){
                 userTask= ((UserTask) flowElement);
                break;
            }
        }

        return userTask;
    }

    /**
     * 判断是否是最后一个审批节点
     * @param taskId
     * @param activityId
     * @return
     * @throws Exception
     */
    public static Map<String,String> isFinalTask(String taskId,String activityId)throws Exception{
        // 获取当前活动节点ID
        if (StringUtils.isEmpty(activityId)) {
            activityId = findTaskById(taskId).getTaskDefinitionKey();
        }

        Map<String,String> map=new HashMap<>();
       // TaskDefinition task = null;
        //根据任务id获取流程定义
        ProcessDefinitionEntity processDefinitionEntityByTaskId = findProcessDefinitionEntityByTaskId(taskId);
        //获取流程所有节点信息
        List<ActivityImpl> activitiList = processDefinitionEntityByTaskId.getActivities();
        //根据任务id获取流程实例
        ProcessInstance processInstance = findProcessInstanceByTaskId(taskId);
        String processInstanceId = processInstance.getId();
        //当前流程节点Id信息
      //  String activityId =processInstance.getActivityId();
        List<String> activityId_list=new ArrayList<>();
        //遍历所有节点信息
        for(ActivityImpl activityImpl : activitiList){
            //this.parent instanceof ActivityImpl ? (ActivityImpl)this.parent : null;
            if("userTask".equals(activityImpl.getProperty("type"))){
                activityId_list.add(activityImpl.getId());
            }
        }

        if(activityId.equals(activityId_list.get(activityId_list.size()-1))) map.put("tf","true");
        else map.put("tf","false");
        map.put("processKey",processInstance.getProcessDefinitionKey());
        map.put("bid",processInstance.getBusinessKey());
        return map;
    }
    /**
     * 获取下一节点
     * @param taskId
     * @return
     * @throws Exception
     */
    public static TaskDefinition getNextTask(String taskId)throws Exception{
        String id = null;
        TaskDefinition task = null;
        //根据任务id获取流程定义
        ProcessDefinitionEntity processDefinitionEntityByTaskId = findProcessDefinitionEntityByTaskId(taskId);
        //获取流程所有节点信息
        List<ActivityImpl> activitiList = processDefinitionEntityByTaskId.getActivities();
        //根据任务id获取流程实例
        ProcessInstance processInstance = findProcessInstanceByTaskId(taskId);
        String processInstanceId = processInstance.getId();
        //当前流程节点Id信息
        String activitiId =processInstance.getActivityId();
        //遍历所有节点信息
        for(ActivityImpl activityImpl : activitiList){
            id = activityImpl.getId();

            // 找到当前节点信息
            if (activitiId.equals(id)) {

                //获取下一个节点信息
                task = nextTaskDefinition(activityImpl, activityImpl.getId(), null, processInstanceId);

                break;
            }
        }

        return task;
    }

    /**
     * 下一个任务节点信息,
     *
     * 如果下一个节点为用户任务则直接返回,
     *
     * 如果下一个节点为排他网关, 获取排他网关Id信息, 根据排他网关Id信息和execution获取流程实例排他网关Id为key的变量值,
     * 根据变量值分别执行排他网关后线路中的el表达式, 并找到el表达式通过的线路后的用户任务信息
     * @param  activityImpl     流程节点信息
     * @param  activityId             当前流程节点Id信息
     * @param  elString               排他网关顺序流线段判断条件, 例如排他网关顺序留线段判断条件为${money>1000}, 若满足流程启动时设置variables中的money>1000, 则流程流向该顺序流信息
     * @param  processInstanceId      流程实例Id信息
     * @return
     */
    private static TaskDefinition nextTaskDefinition(ActivityImpl activityImpl, String activityId, String elString, String processInstanceId){

        PvmActivity ac = null;

        Object s = null;

        //如果遍历节点为用户任务并且节点不是当前节点信息
        if("userTask".equals(activityImpl.getProperty("type")) && !activityId.equals(activityImpl.getId())){
            //获取该节点下一个节点信息
            TaskDefinition taskDefinition = ((UserTaskActivityBehavior)activityImpl.getActivityBehavior()).getTaskDefinition();
            return taskDefinition;
        }else{
            //获取节点所有流向线路信息
            List<PvmTransition> outTransitions = activityImpl.getOutgoingTransitions();
            List<PvmTransition> outTransitionsTemp = null;
            for(PvmTransition tr : outTransitions){
                ac = tr.getDestination(); //获取线路的终点节点
                //如果流向线路为排他网关
                if("exclusiveGateway".equals(ac.getProperty("type"))){
                    outTransitionsTemp = ac.getOutgoingTransitions();

                    //如果网关路线判断条件为空信息
                    if(StringUtils.isEmpty(elString)) {
                        //获取流程启动时设置的网关判断条件信息
                        elString = getGatewayCondition(ac.getId(), processInstanceId);
                    }

                    //如果排他网关只有一条线路信息
                    if(outTransitionsTemp.size() == 1){
                        return nextTaskDefinition((ActivityImpl)outTransitionsTemp.get(0).getDestination(), activityId, elString, processInstanceId);
                    }else if(outTransitionsTemp.size() > 1){  //如果排他网关有多条线路信息
                        for(PvmTransition tr1 : outTransitionsTemp){
                            s = tr1.getProperty("conditionText");  //获取排他网关线路判断条件信息
                            //判断el表达式是否成立
                            if(isCondition(ac.getId(), StringUtils.trim(s.toString()), elString)){
                                return nextTaskDefinition((ActivityImpl)tr1.getDestination(), activityId, elString, processInstanceId);
                            }
                        }
                    }
                }else if("userTask".equals(ac.getProperty("type"))){
                    return ((UserTaskActivityBehavior)((ActivityImpl)ac).getActivityBehavior()).getTaskDefinition();
                }else{
                }
            }
            return null;
        }
    }
    /**
     * 查询流程启动时设置排他网关判断条件信息
     * @param  gatewayId          排他网关Id信息, 流程启动时设置网关路线判断条件key为网关Id信息
     * @param  processInstanceId  流程实例Id信息
     * @return
     */
    public static String getGatewayCondition(String gatewayId, String processInstanceId) {
        Execution execution = runtimeService.createExecutionQuery().processInstanceId(processInstanceId).singleResult();
        return runtimeService.getVariable(execution.getId(), gatewayId).toString();
    }

    /**
     * 根据key和value判断el表达式是否通过信息
     * @param  key    el表达式key信息
     * @param  el     el表达式信息
     * @param  value  el表达式传入值信息
     * @return
     */
    public static boolean isCondition(String key, String el, String value) {
        ExpressionFactory factory = new ExpressionFactoryImpl();
        SimpleContext context = new SimpleContext();
        context.setVariable(key, factory.createValueExpression(value, String.class));
        ValueExpression e = factory.createValueExpression(context, el, boolean.class);
        return (Boolean) e.getValue(context);
    }
    public static FormService getFormService() {
        return formService;
    }

    public static HistoryService getHistoryService() {
        return historyService;
    }


    public static ProcessEngine getProcessEngine() {
        return processEngine;
    }

    public static RepositoryService getRepositoryService() {
        return repositoryService;
    }

    public static RuntimeService getRuntimeService() {
        return runtimeService;
    }

    public static TaskService getTaskService() {
        return taskService;
    }


}
